home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 142 / Gekkan Dennou Club - 2000.3 Vol. 142 (Japan).7z / Gekkan Dennou Club - 2000.3 Vol. 142 (Japan) (Track 1).bin / ikap / etc2 / src.lzh / tr68k.c < prev    next >
C/C++ Source or Header  |  2000-02-04  |  30KB  |  1,250 lines

  1. /* 楽器の弾けない私から、楽器の弾けない貴方へ */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sys/dos.h>
  6. #include <sys/iocs.h>
  7. #include <sys/xglob.h>
  8.  
  9. #define GLOBAL_DEFINE        /* グローバル変数を確保する */
  10. #include "tr68k.h"
  11. #include "sound.h"
  12. #include "pcm8call.h"
  13.  
  14.  
  15. #define SC_BGX    12        /* 楽譜?部の BGTEXT 上の座標 */
  16. #define SC_BGY    16
  17. #define ACTIVE_BGX    29
  18.  
  19. #define TEMPO_BGX    3    /* テンポ表示(数字)の BGTEXT 上の座標 */
  20. #define TEMPO_BGY    12
  21.  
  22. #define COPY_BGX    12    /* [COPY] の BGTEXT 上の座標 */
  23. #define COPY_BGY    26
  24. #define PASTE_BGX    14    /* [PASTE] の BGTEXT 上の座標 */
  25. #define PASTE_BGY    26
  26. #define SAVE_BGX    26    /* [SAVE] の BGTEXT 上の座標 */
  27. #define SAVE_BGY    26
  28.  
  29. #define CHASE_BGX    4    /* [CHASE] の BGTEXT 上の座標 */
  30. #define CHASE_BGY    27
  31. #define LOOP_BGX    2    /* [LOOP] の BGTEXT 上の座標 */
  32. #define LOOP_BGY    27
  33.  
  34. #define BARNO_BGX    19    /* 小節表示(数字)の BGTEXT 上の座標 */
  35. #define BARNO_BGY    12
  36. #define MAXBARNO_BGX    24    /* 最大小節表示(数字)の BGTEXT 上の座標 */
  37. #define MAXBARNO_BGY    BARNO_BGY
  38.  
  39. /* BG テキストの番号 */
  40. #define BG_NOTE        0x10    /* 音符 */
  41.  
  42. /* パレットの番号<<16 */
  43. #define PAL_TYPE0    0x0200    /* 音色タイプ0のパレット */
  44. #define PAL_FLASH    0x0600    /* 光る音符のパレット */
  45. #define PAL_NUMBER    0x0200    /* 数字のパレット */
  46.  
  47. /* BG テキスト+パレット<<16の番号 */
  48. #define BGPAL_UPDOWN    0x022b    /* 矢印 */
  49. #define BGPAL_TRACK_ACTIVE        0x023d
  50. #define BGPAL_TRACK_INACTIVE    0x022d
  51. #define BGPAL_BUTTON32    0x022e
  52. #define BGPAL_BUTTON32_UP    0x024e
  53. #define BGPAL_LAMP_ACTIVE    0x065d
  54. #define BGPAL_LAMP_INACTIVE    0x054d
  55.  
  56. #define REPEAT_1ST    30    /* 最初にキーリピートするまでの時間 */
  57. #define REPEAT_2ND    5    /* 2回目以降キーリピートするまでの時間 */
  58.  
  59. static char track_active[TRACK_MAX];    /* トラックが有効か(画面左端のランプ) */
  60. static char copy_volume[TRACK_MAX][NOTE_DISP];    /* コピーバッファ */
  61. static char copy_type[TRACK_MAX][NOTE_DISP];
  62.  
  63.  
  64. static int tempo;        /* VDISP60SEC/tempo 回が note_tempo */
  65. static int chase = 0;        /* 演奏中の小節を追いかけるか */
  66. static int loop = 0;        /* 現在演奏中の小節をループするか */
  67. static int pause = 0;        /* ポーズ中 */
  68.  
  69. static int bar_disp = 0;    /* 現在表示中の小節 */
  70. static int bar_play = 0;    /* 現在演奏中の小節 */
  71. static int type_current = 0;
  72. #define RGB(r,g,b) ((g)<<11|(r)<<6|(b)<<1)
  73.  
  74.  
  75. /* イベントフラグ */
  76. enum {
  77.     EVENT_MSLRUP = 0, EVENT_MSLDOWN, EVENT_MSRDOWN, EVENT_MSLRDOWN, EVENT_KEYDOWN,
  78. };
  79.  
  80.  
  81. /* イベント構造体 */
  82. typedef struct {
  83.     char type;        /* イベントの種類 */
  84.     char old_type;        /* イベントの種類 */
  85.     unsigned short mouse_x;    /* マウスカーソルの座標 */
  86.     unsigned short mouse_y;
  87.     unsigned short mouse_button;
  88.     unsigned short mouse_pat;
  89.     unsigned short old_mouse_x;    /* 前のマウスカーソルの座標 */
  90.     unsigned short old_mouse_y;
  91.     unsigned short old_mouse_pat;
  92.     int keycode;        /* キーコード */
  93.     int work1, work2;
  94.     char shift_key;        /* =!0:シフトキーが押されている */
  95. } EVENTREC;
  96.  
  97. /* キーコード */
  98. enum {
  99.     KEYDOWN_NON = 0, KEYDOWN_LEFT, KEYDOWN_RIGHT, KEYDOWN_ESC, KEYDOWN_BREAK,
  100.     KEYDOWN_UP, KEYDOWN_DOWN, KEYDOWN_ROLLUP, KEYDOWN_ROLLDOWN, KEYDOWN_UNDO, KEYDOWN_DEL,
  101.     KEYDOWN_XF1, KEYDOWN_XF2,
  102.     KEYDOWN_Z, KEYDOWN_X, KEYDOWN_C, KEYDOWN_V,
  103.     KEYDOWN_SPACE,
  104. };
  105.  
  106. static char *sp_data = NULL;
  107. static char *pal_data = NULL;
  108. static int screen_init = 0;
  109.  
  110. extern int apic_load (char *, int, int);
  111.  
  112.  
  113.  
  114. void usage (void)
  115. {
  116.     puts ("Moland TR-68K ver0.90909\n"
  117.           "        programmed by Mitsuky <FreeSoftware>\n"
  118.           "TR シリーズ風リズムマシンです\n"
  119.           "使用法 : TR68K [.ZMSファイル名]\n"
  120.           ".ZMSファイル名無指定時には TR68K.ZMS を読み込みます\n"
  121.         );
  122. }
  123.  
  124.  
  125.  
  126. /* アップダウンボタンを1セット表示 */
  127. void DispUpdown (int x, int y)
  128. {
  129.     _iocs_bgtextst (0, x, y, BGPAL_UPDOWN);
  130.     _iocs_bgtextst (0, x + 1, y, BGPAL_UPDOWN + 1);
  131.     _iocs_bgtextst (0, x, y + 1, BGPAL_UPDOWN + 0x10);
  132.     _iocs_bgtextst (0, x + 1, y + 1, BGPAL_UPDOWN + 0x11);
  133. }
  134.  
  135.  
  136. /* 数字を1個表示 */
  137. void DispOneNumber (int x, int y, int no)
  138. {
  139.     _iocs_bgtextst (0, x, y, PAL_NUMBER + 0x20 + no);
  140.     _iocs_bgtextst (0, x, y + 1, PAL_NUMBER + 0x30 + no);
  141. }
  142.  
  143.  
  144.  
  145. /* 2桁の数字を表示 */
  146. void DispTwoNumber (int x, int y, int no)
  147. {
  148.     int n1, n2;
  149.     int flag = 0;
  150.  
  151.     n1 = no / 10;
  152.     n2 = no - n1 * 10;
  153.  
  154.     if (n1 > 0) {
  155.         DispOneNumber (x, y, n1);
  156.         flag = !0;
  157.     } else {
  158.         DispOneNumber (x, y, 10);    /* 10 は LED 消灯表示 */
  159.     }
  160.     DispOneNumber (x + 1, y, n2);
  161. }
  162.  
  163.  
  164.  
  165. /* 3桁の数字を表示 */
  166. void DispThreeNumber (int x, int y, int no)
  167. {
  168.     int n1, n2, n3;
  169.     int flag = 0;
  170.  
  171.     n1 = no / 100;
  172.     n2 = (no - n1 * 100) / 10;
  173.     n3 = (no - n1 * 100 - n2 * 10);
  174.  
  175.     if (n1 > 0) {
  176.         DispOneNumber (x, y, n1);
  177.         flag = !0;
  178.     } else {
  179.         DispOneNumber (x, y, 10);    /* 10 は LED 消灯表示 */
  180.     }
  181.     if ((n2 > 0) || (flag)) {
  182.         DispOneNumber (x + 1, y, n2);
  183.     } else {
  184.         DispOneNumber (x + 1, y, 10);    /* 10 は LED 消灯表示 */
  185.     }
  186.     DispOneNumber (x + 2, y, n3);
  187. }
  188.  
  189.  
  190.  
  191.  
  192. /* 音符を光らせる */
  193. void FlashNote (int note_no)
  194. {
  195.     static int old_bar_disp = 0;
  196.     static int old_note_no = 0;
  197.     int j;
  198.  
  199.     if (old_bar_disp == bar_disp) {
  200.         for (j = 0; j < TRACK_MAX; j++)
  201.             if (track_active[j])
  202.                 _iocs_bgtextst (0, SC_BGX + old_note_no, SC_BGY + j,
  203.                         PAL_TYPE0 + (note_type[j][bar_disp * NOTE_DISP + old_note_no] << 8) + BG_NOTE + note_volume[j][bar_disp * NOTE_DISP + old_note_no]);
  204.             else
  205.                 _iocs_bgtextst (0, SC_BGX + old_note_no, SC_BGY + j,
  206.                         PAL_TYPE0 + BG_NOTE);
  207.     }
  208.     old_bar_disp = bar_disp;
  209.  
  210.     if (bar_play == bar_disp) {
  211.         for (j = 0; j < TRACK_MAX; j++)
  212.             if (track_active[j])
  213.                 _iocs_bgtextst (0, SC_BGX + note_no, SC_BGY + j,
  214.                         PAL_FLASH + BG_NOTE + note_volume[j][bar_disp * NOTE_DISP + note_no]);
  215.             else
  216.                 _iocs_bgtextst (0, SC_BGX + note_no, SC_BGY + j,
  217.                         PAL_FLASH + BG_NOTE);
  218.     }
  219.     old_note_no = note_no;
  220. }
  221.  
  222.  
  223.  
  224. /* 32x32ドットのボタンを表示 */
  225. void DispButton32 (int x, int y, int s)
  226. {
  227.     switch (s) {
  228.     case 0:
  229.         _iocs_bgtextst (0, x, y, BGPAL_BUTTON32);
  230.         _iocs_bgtextst (0, x + 1, y, BGPAL_BUTTON32 + 1);
  231.         _iocs_bgtextst (0, x, y + 1, BGPAL_BUTTON32 + 0x10);
  232.         _iocs_bgtextst (0, x + 1, y + 1, BGPAL_BUTTON32 + 0x11);
  233.         break;
  234.     case 1:
  235.         _iocs_bgtextst (0, x, y, BGPAL_BUTTON32_UP);
  236.         _iocs_bgtextst (0, x + 1, y, BGPAL_BUTTON32_UP + 1);
  237.         _iocs_bgtextst (0, x, y + 1, BGPAL_BUTTON32_UP + 0x10);
  238.         _iocs_bgtextst (0, x + 1, y + 1, BGPAL_BUTTON32_UP + 0x11);
  239.         break;
  240.     case 2:
  241.         _iocs_bgtextst (0, x, y, BGPAL_BUTTON32_UP);
  242.         _iocs_bgtextst (0, x + 1, y, BGPAL_BUTTON32_UP + 1);
  243.         _iocs_bgtextst (0, x, y + 1, BGPAL_BUTTON32_UP + 0x10);
  244.         _iocs_bgtextst (0, x + 1, y + 1, BGPAL_BUTTON32_UP + 0x11);
  245.         break;
  246.     }
  247. }
  248.  
  249.  
  250.  
  251. /* トラックアクティブ状態を表示 */
  252. void DispTrackActive (int track)
  253. {
  254.     if (track_active[track])
  255.         _iocs_bgtextst (0, ACTIVE_BGX, SC_BGY + track, BGPAL_TRACK_ACTIVE);
  256.     else
  257.         _iocs_bgtextst (0, ACTIVE_BGX, SC_BGY + track, BGPAL_TRACK_INACTIVE);
  258. }
  259.  
  260.  
  261.  
  262. /* ランプ付き16x16ドットのボタンを表示 */
  263. void DispButtonLamp (int x, int y, int s)
  264. {
  265.     if (s)
  266.         _iocs_bgtextst (0, x, y, BGPAL_LAMP_ACTIVE);
  267.     else
  268.         _iocs_bgtextst (0, x, y, BGPAL_LAMP_INACTIVE);
  269. }
  270.  
  271.  
  272.  
  273. /* 1小節表示 */
  274. /* 小節を英語で言うと "bar" たそうで */
  275. void DispScore (int bar_disp)
  276. {
  277.     int i, j;
  278.  
  279.     for (j = 0; j < TRACK_MAX; j++) {
  280.         if (track_active[j]) {
  281.             for (i = 0; i < NOTE_DISP; i++)
  282.                 _iocs_bgtextst (0, SC_BGX + i, SC_BGY + j,
  283.                         PAL_TYPE0 + (note_type[j][bar_disp * NOTE_DISP + i] << 8) + BG_NOTE + note_volume[j][bar_disp * NOTE_DISP + i]);
  284.         } else {
  285.             for (i = 0; i < NOTE_DISP; i++)
  286.                 _iocs_bgtextst (0, SC_BGX + i, SC_BGY + j, PAL_TYPE0 + (note_type[j][bar_disp * NOTE_DISP + i] << 8) + BG_NOTE);
  287.         }
  288.     }
  289. }
  290.  
  291.  
  292.  
  293. /* .PCM ファイル名を表示&マウスカーソルの色を設定 */
  294. void DispFname (void)
  295. {
  296.     int i;
  297.     int color_mouse[TYPE_MAX] =
  298.     {RGB (31, 0, 0), RGB (0, 31, 0), RGB (0, 0, 31), RGB (31, 31, 0)};
  299.  
  300. #define FNAME_X    2        /* ファイル名表示座標 */
  301. #define FNAME_Y    SC_BGY
  302.  
  303.     /* マウスカーソルの色を設定 */
  304.     _iocs_tpalet (8, color_mouse[type_current]);
  305.  
  306.     for (i = 0; i < TRACK_MAX; i++) {
  307.         _dos_c_locate (FNAME_X, FNAME_Y + i);
  308.         puts ("                        ");
  309.         _dos_c_locate (FNAME_X, FNAME_Y + i);
  310.         puts (pcm_fname[type_current][i]);
  311.     }
  312. }
  313.  
  314.  
  315.  
  316. /* 左クリックで音符(?)を置く */
  317. void PutNote (int track, int note, int volume, int type)
  318. {
  319.     if (track_active[track]) {
  320.         note_volume[track][bar_disp * NOTE_DISP + note] = volume;
  321.         note_type[track][bar_disp * NOTE_DISP + note] = type;
  322.         _iocs_bgtextst (0, SC_BGX + note, SC_BGY + track,
  323.                 PAL_TYPE0 + (type << 8) + BG_NOTE + volume);
  324.     }
  325. }
  326.  
  327.  
  328.  
  329. /* 指定した音符上にマウスカーソルを移動する・KEYDOWN イベント用 */
  330. /* dx,dy は note,track の移動量 */
  331. void SetMousePos (EVENTREC * eventrec, int dx, int dy)
  332. {
  333.     int mouse_x = eventrec->mouse_x;
  334.     int mouse_y = eventrec->mouse_y;
  335.     int track, note;
  336.  
  337.     if (mouse_x >= SC_BGX * 16) {
  338.         if (mouse_x < (SC_BGX + NOTE_DISP) * 16) {
  339.             /* X座標が楽譜内の場合 */
  340.             note = (mouse_x - SC_BGX * 16) / 16;
  341.             note += dx;
  342.             if (note < 0) {
  343.                 note = NOTE_DISP - 1;
  344.                 if (--bar_disp < 0)    /* 1小節戻る */
  345.                     bar_disp = bar_max_table[bar_max] - 1;
  346.                 DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  347.                 DispScore (bar_disp);
  348.             }
  349.             if (note >= NOTE_DISP) {
  350.                 note = 0;
  351.                 if (++bar_disp >= bar_max_table[bar_max])    /* 1小節先へ */
  352.                     bar_disp = 0;
  353.                 DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  354.                 DispScore (bar_disp);
  355.             }
  356.         } else {
  357.             note = NOTE_DISP - 1;
  358.         }
  359.     } else {
  360.         note = 0;
  361.     }
  362.     if (mouse_y >= SC_BGY * 16) {
  363.         if (mouse_y < (SC_BGY + TRACK_MAX) * 16) {
  364.             /* Y座標が楽譜内の場合 */
  365.             track = (mouse_y - SC_BGY * 16) / 16;
  366.             track += dy;
  367.             if (track < 0)
  368.                 track = TRACK_MAX - 1;
  369.             else if (track >= TRACK_MAX)
  370.                 track = 0;
  371.         } else {
  372.             track = TRACK_MAX - 1;
  373.         }
  374.     } else {
  375.         track = 0;
  376.     }
  377.  
  378. #define MOUSE_OFFSET_X    12
  379. #define MOUSE_OFFSET_Y    12
  380.     _iocs_ms_curst (SC_BGX * 16 + note * 16 + MOUSE_OFFSET_X, SC_BGY * 16 + track * 16 + MOUSE_OFFSET_Y);
  381. }
  382.  
  383.  
  384.  
  385. /* マウスカーソル上の音符をの音量を変更する・KEYDOWN イベント用 */
  386. /* dv = 増減する値 0なら音符を消す */
  387. void SetVolume (EVENTREC * eventrec, int dv)
  388. {
  389.     if ((eventrec->mouse_x >= SC_BGX * 16) && (eventrec->mouse_x < (SC_BGX + NOTE_DISP) * 16)
  390.         && (eventrec->mouse_y >= SC_BGY * 16) && (eventrec->mouse_y < (SC_BGY + TRACK_MAX) * 16)) {
  391.         int note, track;
  392.         int type, volume;
  393.         note = (eventrec->mouse_x - SC_BGX * 16) / 16;
  394.         track = (eventrec->mouse_y - SC_BGY * 16) / 16;
  395.  
  396.         type = note_type[track][bar_disp * NOTE_DISP + note];
  397.         volume = note_volume[track][bar_disp * NOTE_DISP + note];
  398.         if (volume == 0) {
  399.             PutNote (track, note, 8, type_current);
  400.         } else {
  401.             if (dv)
  402.                 volume += dv;
  403.             else
  404.                 volume = 0;
  405.             if (volume <= 0)
  406.                 volume = 0;
  407.             else if (volume > 15)
  408.                 volume = 15;
  409.             PutNote (track, note, volume, type);
  410.         }
  411.     }
  412. }
  413.  
  414.  
  415.  
  416. /* [Z][X][C][V] で直接音符を置く・KEYDOWN イベント用 */
  417. void SetAbsNote (EVENTREC * eventrec, int type)
  418. {
  419.     if ((eventrec->mouse_x >= SC_BGX * 16) && (eventrec->mouse_x < (SC_BGX + NOTE_DISP) * 16)
  420.         && (eventrec->mouse_y >= SC_BGY * 16) && (eventrec->mouse_y < (SC_BGY + TRACK_MAX) * 16)) {
  421.         int note, track;
  422.         int volume;
  423.         note = (eventrec->mouse_x - SC_BGX * 16) / 16;
  424.         track = (eventrec->mouse_y - SC_BGY * 16) / 16;
  425.  
  426.         volume = note_volume[track][bar_disp * NOTE_DISP + note];
  427.         if (volume == 0){
  428.             volume = 8;
  429.         }else{
  430.             type_current = type;
  431.             DispFname();
  432.         }
  433.         PutNote (track, note, volume, type);
  434.     }
  435. }
  436.  
  437.  
  438.  
  439. void WaitClick (void)
  440. {
  441.     while (_iocs_ms_getdt () & 0xff00);    /* 左ボタンが離されるのを待つ */
  442.     while (!(_iocs_ms_getdt () & 0xff00));    /* 左ボタンが押されるのを待つ */
  443.     while (_iocs_ms_getdt () & 0xff00);    /* 左ボタンが離されるのを待つ */
  444. }
  445.  
  446.  
  447.  
  448. /* 演奏データをセーブする */
  449. void SaveScore (char *fname)
  450. {
  451. #define MES_X    0
  452. #define MES_Y    28
  453.     _dos_c_locate (MES_X, MES_Y);
  454.  
  455.     if (SoundSaveZms (fname) < 0) {
  456.         printf ("%s を書き込めません\n", fname);
  457.     } else {
  458.         if (fname == NULL)
  459.             printf ("TEMP.ZMS を書き込みました\n");
  460.         else
  461.             printf ("%s を書き込みました\n", fname);
  462.     }
  463.  
  464.     printf ("マウスをクリックして下さい\n");
  465.     WaitClick ();
  466.     _dos_c_locate (MES_X, MES_Y);
  467.     puts ("                                    \n"
  468.           "                          \n");
  469. }
  470.  
  471.  
  472.  
  473. void WaitVdisp (void)
  474. {
  475.     int sp;
  476.     volatile unsigned char *GPIP_DATA = (volatile unsigned char *) 0xe88001;
  477.  
  478.     sp = _iocs_b_super (0);
  479.     while (!((*GPIP_DATA) & 0x10));
  480.     while ((*GPIP_DATA) & 0x10);
  481.     _iocs_b_super (sp);
  482. }
  483.  
  484.  
  485.  
  486. void PcmOut (int note)
  487. {
  488.     int track;
  489.  
  490.     for (track = 0; track < TRACK_MAX; track++) {
  491.         int volume = note_volume[track][bar_play * NOTE_DISP + note];
  492.         int type = note_type[track][bar_play * NOTE_DISP + note];
  493.         if ((volume) && (track_active[track]))
  494.             SoundPcm8Out (track, type, volume);
  495.     }
  496. }
  497.  
  498.  
  499.  
  500. /* どの場所でマウスの左/右ボタンが押されたか */
  501. /* 返り値: BPOS_???, eventrec->work1,work2 = その詳細(ボタンによって違う) */
  502. enum {
  503.     BPOS_NON = 0, BPOS_SCORE, BPOS_FNAME, BPOS_ACTIVE, BPOS_TEMPO, BPOS_CURRENT, BPOS_MAX,
  504.     BPOS_COPY, BPOS_PASTE, BPOS_SAVE, BPOS_CHASE, BPOS_LOOP,
  505. };
  506. int SearchButton (EVENTREC * eventrec)
  507. {
  508.     int ret = 1;
  509.     struct {
  510.         int x0, y0, x1, y1;
  511.     } rect[] = {
  512.         {        /* なし */
  513.             0, 0, 0, 0
  514.         },
  515.         {        /* 楽譜上 */
  516.             SC_BGX *16, SC_BGY * 16, SC_BGX * 16 + NOTE_DISP * 16, SC_BGY * 16 + TRACK_MAX * 16
  517.         },
  518.         {        /* debug ファイル名上 */
  519.             0, 0, 0, 0
  520.         },
  521.         {        /* アクティブボタン上 */
  522.             ACTIVE_BGX *16, SC_BGY * 16, ACTIVE_BGX * 16 + 16, SC_BGY * 16 + TRACK_MAX * 16
  523.         },
  524.         {        /* TEMPO アップダウンボタン */
  525.             (TEMPO_BGX + 3) * 16, TEMPO_BGY * 16, (TEMPO_BGX + 3) * 16 + 32, TEMPO_BGY * 16 + 32
  526.         },
  527.         {        /* CURRENT アップダウンボタン */
  528.             (BARNO_BGX + 2) * 16, BARNO_BGY * 16, (BARNO_BGX + 2) * 16 + 32, BARNO_BGY * 16 + 32
  529.         },
  530.         {        /* MAX アップダウンボタン */
  531.             (MAXBARNO_BGX + 2) * 16, MAXBARNO_BGY * 16, (MAXBARNO_BGX + 2) * 16 + 32, MAXBARNO_BGY * 16 + 32
  532.         },
  533.         {
  534.             COPY_BGX *16, COPY_BGY * 16, COPY_BGX * 16 + 32, COPY_BGY * 16 + 32
  535.         },
  536.         {
  537.             PASTE_BGX *16, PASTE_BGY * 16, PASTE_BGX * 16 + 32, PASTE_BGY * 16 + 32
  538.         },
  539.         {
  540.             SAVE_BGX *16, SAVE_BGY * 16, SAVE_BGX * 16 + 32, SAVE_BGY * 16 + 32
  541.         },
  542.         {
  543.             CHASE_BGX *16, CHASE_BGY * 16, CHASE_BGX * 16 + 16, CHASE_BGY * 16 + 16
  544.         },
  545.         {
  546.             LOOP_BGX *16, LOOP_BGY * 16, LOOP_BGX * 16 + 16, LOOP_BGY * 16 + 16
  547.         },
  548.  
  549.         {        /* エンドコード */
  550.             -1, -1, -1, -1
  551.         },
  552.     };
  553.  
  554.     for (;;) {
  555.         if (rect[ret].x0 < 0) {
  556.             ret = 0;
  557.             break;
  558.         }
  559.         if ((eventrec->mouse_x >= rect[ret].x0) && (eventrec->mouse_x < rect[ret].x1)
  560.         && (eventrec->mouse_y >= rect[ret].y0) && (eventrec->mouse_y < rect[ret].y1)) {
  561.             switch (ret) {
  562.             case BPOS_NON:
  563.             default:
  564.                 break;
  565.             case BPOS_SCORE:
  566.                 eventrec->work1 = (eventrec->mouse_x - SC_BGX * 16) / 16;    /* note_no */
  567.                 eventrec->work2 = (eventrec->mouse_y - SC_BGY * 16) / 16;    /* track_no */
  568.                 break;
  569.             case BPOS_FNAME:
  570.                 break;
  571.             case BPOS_ACTIVE:
  572.                 /* どのトラックのボタンが押されたかを work1 に返す */
  573.                 eventrec->work1 = (eventrec->mouse_y - SC_BGY * 16) / 16;    /* track_no */
  574.                 break;
  575.             case BPOS_TEMPO:
  576.             case BPOS_CURRENT:
  577.             case BPOS_MAX:
  578.                 /* アップボタンかダウンボタンかを work1 に返す */
  579.                 eventrec->work1 = (eventrec->mouse_x < rect[ret].x0 + 16);
  580.                 break;
  581.             }
  582.             break;
  583.         }
  584.         ret++;
  585.     }
  586.  
  587.     return (ret);
  588. }
  589.  
  590.  
  591.  
  592. /* キー入力をチェック */
  593. void CheckKey (EVENTREC * eventrec)
  594. {
  595.     int k;
  596.  
  597.     eventrec->keycode = KEYDOWN_NON;
  598.  
  599. #define KEY_ESC    2
  600.     if (_iocs_bitsns (0) & KEY_ESC)
  601.         eventrec->keycode = KEYDOWN_ESC;
  602.  
  603. #define KEY_Z    0x04
  604. #define KEY_X    0x08
  605. #define KEY_C    0x10
  606. #define KEY_V    0x20
  607.     k = _iocs_bitsns (0x05);
  608.     if (k & KEY_Z)
  609.         eventrec->keycode = KEYDOWN_Z;
  610.     if (k & KEY_X)
  611.         eventrec->keycode = KEYDOWN_X;
  612.     if (k & KEY_C)
  613.         eventrec->keycode = KEYDOWN_C;
  614.     if (k & KEY_V)
  615.         eventrec->keycode = KEYDOWN_V;
  616.  
  617. #define KEY_DEL    0x80
  618. #define KEY_SPACE    0x20
  619.     k = _iocs_bitsns (0x06);
  620.     if (k & KEY_DEL)
  621.         eventrec->keycode = KEYDOWN_DEL;
  622.     if (k & KEY_SPACE)
  623.         eventrec->keycode = KEYDOWN_SPACE;
  624.  
  625. #define KEY_ROLLUP    0x01
  626. #define KEY_ROLLDOWN    0x02
  627. #define KEY_UNDO    0x04
  628. #define KEY_LEFT    0x08
  629. #define KEY_UP        0x10
  630. #define KEY_RIGHT    0x20
  631. #define KEY_DOWN    0x40
  632.     k = _iocs_bitsns (0x07);
  633.     if (k & KEY_LEFT)
  634.         eventrec->keycode = KEYDOWN_LEFT;
  635.     if (k & KEY_RIGHT)
  636.         eventrec->keycode = KEYDOWN_RIGHT;
  637.     if (k & KEY_UP)
  638.         eventrec->keycode = KEYDOWN_UP;
  639.     if (k & KEY_DOWN)
  640.         eventrec->keycode = KEYDOWN_DOWN;
  641.     if (k & KEY_ROLLUP)
  642.         eventrec->keycode = KEYDOWN_ROLLUP;
  643.     if (k & KEY_ROLLDOWN)
  644.         eventrec->keycode = KEYDOWN_ROLLDOWN;
  645.     if (k & KEY_UNDO)
  646.         eventrec->keycode = KEYDOWN_UNDO;
  647.  
  648. #define KEY_XF1    0x20
  649. #define KEY_XF2    0x40
  650.     k = _iocs_bitsns (0x0a);
  651.     if (k & KEY_XF1)
  652.         eventrec->keycode = KEYDOWN_XF1;
  653.     if (k & KEY_XF2)
  654.         eventrec->keycode = KEYDOWN_XF2;
  655.  
  656. #define KEY_BREAK    2
  657.     if (_iocs_bitsns (0x0c) & KEY_BREAK)
  658.         eventrec->keycode = KEYDOWN_BREAK;
  659.  
  660.     if (eventrec->keycode != KEYDOWN_NON)
  661.         eventrec->type = EVENT_KEYDOWN;
  662. }
  663.  
  664.  
  665.  
  666. /* イベントを取得する */
  667. void GetEvent (EVENTREC * eventrec)
  668. {
  669.     unsigned int ms_pos, ms_getdt;
  670. #define MS_BUTTON_LEFT    0xff00
  671. #define MS_BUTTON_RIGHT    0x00ff
  672.  
  673.     ms_pos = _iocs_ms_curgt ();
  674.     ms_getdt = _iocs_ms_getdt ();
  675.  
  676.     eventrec->old_type = eventrec->type;
  677.     eventrec->old_mouse_x = eventrec->mouse_x;
  678.     eventrec->old_mouse_y = eventrec->mouse_y;
  679.     eventrec->old_mouse_pat = eventrec->mouse_pat;
  680.     eventrec->mouse_x = (ms_pos >> 16);
  681.     eventrec->mouse_y = (ms_pos & 0xffff);
  682.  
  683.     if (ms_getdt & MS_BUTTON_LEFT) {
  684.         if (ms_getdt & MS_BUTTON_RIGHT)
  685.             eventrec->type = EVENT_MSLRDOWN;
  686.         else
  687.             eventrec->type = EVENT_MSLDOWN;
  688.     } else {
  689.         if (ms_getdt & MS_BUTTON_RIGHT) {
  690.             eventrec->type = EVENT_MSRDOWN;
  691.         } else {
  692.             eventrec->type = EVENT_MSLRUP;
  693.             /* マウスのボタンが押されていない時だけキー入力をチェック */
  694.             CheckKey (eventrec);
  695.         }
  696.     }
  697.  
  698.     /* [SHIFT] キーはキーダウンイベントを発生させないのに注意 */
  699. #define KEY_SHIFT    1
  700.     eventrec->shift_key = (_iocs_bitsns (0x0e) & KEY_SHIFT);
  701.  
  702.     return;
  703. }
  704.  
  705.  
  706.  
  707. void EventLoop (char *fname)
  708. {
  709.     int i, j;
  710.     int note_counter = 0;
  711.     EVENTREC _eventrec, *eventrec = &_eventrec;
  712.     int exit_flag = 0;
  713.     int repeat_time = 0;
  714.  
  715.     int bar_note = 0;    /* 現在演奏中の音符 */
  716.     /* bar_play*NOTE_DISP + note_no が現在演奏中の音符になる */
  717.  
  718.     int button32_up = BPOS_NON;
  719.  
  720.     DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  721.     DispUpdown (BARNO_BGX + 2, BARNO_BGY);
  722.  
  723.     DispTwoNumber (MAXBARNO_BGX, MAXBARNO_BGY, bar_max_table[bar_max]);
  724.     DispUpdown (MAXBARNO_BGX + 2, MAXBARNO_BGY);
  725.  
  726.     tempo = VDISP60SEC / 4 / note_tempo;
  727.     DispThreeNumber (TEMPO_BGX, TEMPO_BGY, tempo);
  728.     DispUpdown (TEMPO_BGX + 3, TEMPO_BGY);
  729.  
  730.     DispButton32 (COPY_BGX, COPY_BGY, 0);
  731.     DispButton32 (PASTE_BGX, PASTE_BGY, 0);
  732.     DispButton32 (SAVE_BGX, SAVE_BGY, 0);
  733.     DispButtonLamp (CHASE_BGX, CHASE_BGY, 0);
  734.     DispButtonLamp (LOOP_BGX, LOOP_BGY, 0);
  735.  
  736.     /* 垂直同期ごとにループ */
  737.     do {
  738.         WaitVdisp ();
  739.  
  740.         /* note_counter が note_tempo を越えるごとに発音 */
  741.         if ((!pause) && (++note_counter >= note_tempo)) {
  742.             note_counter = 0;
  743.             PcmOut (bar_note);    /* 発音 */
  744.             if (++bar_note >= NOTE_DISP) {
  745.                 bar_note = 0;
  746.                 if (!loop) {
  747.                     if (++bar_play >= bar_max_table[bar_max])
  748.                         bar_play = 0;
  749.                     if (chase) {    /* 演奏する小節を追いかけて表示 */
  750.                         bar_disp = bar_play;
  751.                         DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  752.                         DispScore (bar_disp);
  753.                     }
  754.                 }
  755.             }
  756.             FlashNote (bar_note);    /* 音符を光らせる */
  757.             continue;    /* 発音した時はイベントを取得しない(モタり防止) */
  758.         }
  759.         GetEvent (eventrec);    /* イベントを取得 */
  760.         switch (eventrec->type) {
  761.         case EVENT_MSLRUP:
  762.             /* 押した32x32ボタンを戻す処理 */
  763.             switch (button32_up) {
  764.             case BPOS_COPY:
  765.                 DispButton32 (COPY_BGX, COPY_BGY, 0);
  766.                 button32_up = BPOS_NON;
  767.                 break;
  768.             case BPOS_PASTE:
  769.                 DispButton32 (PASTE_BGX, PASTE_BGY, 0);
  770.                 button32_up = BPOS_NON;
  771.                 break;
  772.             case BPOS_SAVE:
  773.                 DispButton32 (SAVE_BGX, SAVE_BGY, 0);
  774.                 button32_up = BPOS_NON;
  775.                 break;
  776.             default:
  777.                 break;
  778.             }
  779.             break;
  780.  
  781.         case EVENT_MSLDOWN:
  782.             /* 押しっぱなし? */
  783.             if (eventrec->type == eventrec->old_type)
  784.                 break;
  785.             switch (SearchButton (eventrec)) {
  786.             case BPOS_NON:
  787.             default:
  788.                 break;
  789.             case BPOS_SCORE:    /* 楽譜上でクリックされた */
  790.                 {
  791.                     int note_no, track_no, volume, type;
  792.  
  793.                     note_no = eventrec->work1;
  794.                     track_no = eventrec->work2;
  795.                     /* 音符を取得する */
  796.                     volume = note_volume[track_no][bar_disp * NOTE_DISP + note_no];
  797.  
  798.                     if (volume == 0) {
  799.                         /* まだ音符が置かれていない時 */
  800.                         volume = 8;
  801.                         type = type_current;
  802.                     } else {
  803.                         /* 既に音符が置かれている時 */
  804.                         if (!eventrec->shift_key) {
  805.                             if (volume < 15)
  806.                                 volume++;
  807.                         } else {
  808.                             /* [SHIFT] 併用の場合は音量を1つ減らす */
  809.                             if (volume > 0)
  810.                                 volume--;
  811.                         }
  812.                         type = note_type[track_no][bar_disp * NOTE_DISP + note_no];
  813.                     }
  814.                     PutNote (track_no, note_no, volume, type);
  815.                 }
  816.                 break;
  817.             case BPOS_FNAME:
  818.                 break;
  819.             case BPOS_ACTIVE:    /* アクティブボタン */
  820.                 track_active[eventrec->work1] = !track_active[eventrec->work1];
  821.                 DispTrackActive (eventrec->work1);
  822.                 DispScore (bar_disp);
  823.                 break;
  824.             case BPOS_TEMPO:
  825.                 if (eventrec->work1) {    /* テンポダウン */
  826.                     note_tempo++;
  827.                     if (note_tempo > 22)
  828.                         note_tempo = 22;
  829.                 } else {    /* テンポアップ */
  830.                     note_tempo--;
  831.                     if (note_tempo < 2)
  832.                         note_tempo = 2;
  833.                 }
  834.                 tempo = VDISP60SEC / 4 / note_tempo;
  835.                 DispThreeNumber (TEMPO_BGX, TEMPO_BGY, tempo);
  836.                 break;
  837.             case BPOS_CURRENT:
  838.                 if (eventrec->work1) {    /* 表示小節ダウン */
  839.                     if (--bar_disp < 0)
  840.                         bar_disp = bar_max_table[bar_max] - 1;
  841.                 } else {    /* 表示小節アップ */
  842.                     if (++bar_disp >= bar_max_table[bar_max])
  843.                         bar_disp = 0;
  844.                 }
  845.                 DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  846.                 DispScore (bar_disp);
  847.                 break;
  848.             case BPOS_MAX:
  849.                 if (eventrec->work1) {    /* 最大小節ダウン */
  850.                     if (--bar_max < 0)
  851.                         bar_max = 4;
  852.                     if (bar_disp >= bar_max_table[bar_max]) {
  853.                         bar_disp = bar_max_table[bar_max] - 1;
  854.                         DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  855.                         DispScore (bar_disp);
  856.                     }
  857.                 } else {    /* 最大小節アップ */
  858.                     if (++bar_max > 4)
  859.                         bar_max = 0;
  860.                 }
  861.                 DispTwoNumber (MAXBARNO_BGX, MAXBARNO_BGY, bar_max_table[bar_max]);
  862.                 break;
  863.             case BPOS_COPY:
  864.                 for (j = 0; j < TRACK_MAX; j++) {
  865.                     for (i = 0; i < NOTE_DISP; i++) {
  866.                         copy_type[j][i] = note_type[j][bar_disp * NOTE_DISP + i];
  867.                         copy_volume[j][i] = note_volume[j][bar_disp * NOTE_DISP + i];
  868.                     }
  869.                 }
  870.                 button32_up = BPOS_COPY;
  871.                 DispButton32 (COPY_BGX, COPY_BGY, 1);
  872.                 break;
  873.             case BPOS_PASTE:
  874.                 for (j = 0; j < TRACK_MAX; j++) {
  875.                     for (i = 0; i < NOTE_DISP; i++) {
  876.                         if (track_active[j]) {
  877.                             note_type[j][bar_disp * NOTE_DISP + i] = copy_type[j][i];
  878.                             note_volume[j][bar_disp * NOTE_DISP + i] = copy_volume[j][i];
  879.                         }
  880.                     }
  881.                 }
  882.                 button32_up = BPOS_PASTE;
  883.                 DispScore (bar_disp);
  884.                 DispButton32 (PASTE_BGX, PASTE_BGY, 1);
  885.                 break;
  886.             case BPOS_SAVE:
  887.                 button32_up = BPOS_SAVE;
  888.                 DispButton32 (SAVE_BGX, SAVE_BGY, 1);
  889.                 SaveScore (fname);
  890.                 break;
  891.             case BPOS_CHASE:
  892.                 chase = !chase;
  893.                 DispButtonLamp (CHASE_BGX, CHASE_BGY, chase);
  894.                 bar_disp = bar_play;
  895.                 DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  896.                 DispScore (bar_disp);
  897.                 break;
  898.             case BPOS_LOOP:
  899.                 loop = !loop;
  900.                 DispButtonLamp (LOOP_BGX, LOOP_BGY, loop);
  901.                 bar_disp = bar_play;
  902.                 DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  903.                 DispScore (bar_disp);
  904.                 break;
  905.             }
  906.             break;
  907.  
  908.         case EVENT_MSRDOWN:
  909.             /* 押しっぱなし? */
  910.             if (eventrec->type == eventrec->old_type)
  911.                 break;
  912.             switch (SearchButton (eventrec)) {
  913.             default:
  914.                 break;
  915.  
  916.             case BPOS_SCORE:    /* 楽譜上でクリックされた */
  917.                 {
  918.                     int note_no, track_no, volume;
  919.  
  920.                     note_no = eventrec->work1;
  921.                     track_no = eventrec->work2;
  922.                     /* 音符を置く */
  923.                     volume = note_volume[track_no][bar_disp * NOTE_DISP + note_no];
  924.  
  925.                     if (volume == 0) {
  926.                         /* 右クリックで色を変える */
  927.                         if (!eventrec->shift_key) {
  928.                             if (++type_current >= TYPE_MAX)
  929.                                 type_current = 0;
  930.                         } else {
  931.                             /* [SHIFT] 併用の場合は色を逆順に */
  932.                             if (--type_current < 0)
  933.                                 type_current = TYPE_MAX - 1;
  934.                         }
  935.                         DispFname ();
  936.                     } else {
  937.                         /* 既に音符が置かれている時 */
  938.                         PutNote (track_no, note_no, 0, 0);    /* 音符を消す */
  939.                     }
  940.                 }
  941.             }
  942.             break;
  943.  
  944.         case EVENT_MSLRDOWN:
  945.             break;
  946.  
  947.         case EVENT_KEYDOWN:
  948.             /* 押しっぱなし? */
  949.             if (eventrec->type == eventrec->old_type) {
  950.                 if (--repeat_time <= 0)
  951.                     repeat_time = REPEAT_2ND;
  952.                 else
  953.                     break;
  954.             } else {
  955.                 repeat_time = REPEAT_1ST;
  956.             }
  957.             switch (eventrec->keycode) {
  958.             case KEYDOWN_LEFT:
  959.                 SetMousePos (eventrec, -1, 0);
  960.                 break;
  961.             case KEYDOWN_RIGHT:
  962.                 SetMousePos (eventrec, 1, 0);
  963.                 break;
  964.             case KEYDOWN_UP:
  965.                 SetMousePos (eventrec, 0, -1);
  966.                 break;
  967.             case KEYDOWN_DOWN:
  968.                 SetMousePos (eventrec, 0, 1);
  969.                 break;
  970.             case KEYDOWN_ROLLUP:
  971.                 SetVolume (eventrec, 1);
  972.                 break;
  973.             case KEYDOWN_ROLLDOWN:
  974.                 SetVolume (eventrec, -1);
  975.                 break;
  976.  
  977.             case KEYDOWN_Z:
  978.                 SetAbsNote (eventrec, 0);
  979.                 break;
  980.             case KEYDOWN_X:
  981.                 SetAbsNote (eventrec, 1);
  982.                 break;
  983.             case KEYDOWN_C:
  984.                 SetAbsNote (eventrec, 2);
  985.                 break;
  986.             case KEYDOWN_V:
  987.                 SetAbsNote (eventrec, 3);
  988.                 break;
  989.  
  990.             case KEYDOWN_UNDO:
  991.                 if (!eventrec->shift_key) {
  992.                     if (++type_current >= TYPE_MAX)
  993.                         type_current = 0;
  994.                 } else {
  995.                     /* [SHIFT] 併用の場合は色を逆順に */
  996.                     if (--type_current < 0)
  997.                         type_current = TYPE_MAX - 1;
  998.                 }
  999.                 DispFname ();
  1000.                 break;
  1001.  
  1002.             case KEYDOWN_DEL:
  1003.             case KEYDOWN_SPACE:
  1004.                 SetVolume (eventrec, 0);
  1005.                 break;
  1006.  
  1007.             case KEYDOWN_XF1:    /* 表示小節ダウン */
  1008.                 if (--bar_disp < 0)
  1009.                     bar_disp = bar_max_table[bar_max] - 1;
  1010.                 DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  1011.                 DispScore (bar_disp);
  1012.                 break;
  1013.             case KEYDOWN_XF2:    /* 表示小節アップ */
  1014.                 if (++bar_disp >= bar_max_table[bar_max])
  1015.                     bar_disp = 0;
  1016.                 DispTwoNumber (BARNO_BGX, BARNO_BGY, bar_disp + 1);
  1017.                 DispScore (bar_disp);
  1018.                 break;
  1019.  
  1020.             case KEYDOWN_ESC:
  1021.                 while (_iocs_bitsns (0) & KEY_ESC);    /* [ESC] が離されるのを待つ */
  1022.                 pause = !pause;
  1023.                 break;
  1024.             case KEYDOWN_BREAK:
  1025.                 exit_flag = !0;
  1026.                 break;
  1027.             default:
  1028.                 break;
  1029.             }
  1030.             break;
  1031.  
  1032.         default:
  1033.             break;
  1034.         }
  1035.     } while (!exit_flag);
  1036. }
  1037.  
  1038.  
  1039.  
  1040. /* ファイルを読み込んでポインタを返す */
  1041. char *LoadFile (char *fname)
  1042. {
  1043.     FILE *fp;
  1044.     char *content;
  1045.     int filesize;
  1046.  
  1047.     fp = fopen (fname, "rb");
  1048.     if (fp == NULL) {
  1049.         /* 実行ファイルと同じパスにしてもう1回オープン */
  1050.         char temp_fname[92];
  1051.         strcpy (temp_fname, mypsp->exe_path);
  1052.         _addlastsep (temp_fname);
  1053.         strcat (temp_fname, fname);
  1054.         fp = fopen (temp_fname, "rb");
  1055.         if (fp == NULL) {
  1056.             printf ("%s を読み込めません\n", fname);
  1057.             return (NULL);
  1058.         }
  1059.     }
  1060.     fseek (fp, 0, SEEK_END);
  1061.     filesize = ftell (fp);
  1062.     fseek (fp, 0, SEEK_SET);
  1063.  
  1064.     content = malloc (filesize);
  1065.     if (content == NULL) {
  1066.         printf ("メモリが足りません\n");
  1067.         fclose (fp);
  1068.         return (NULL);
  1069.     }
  1070.     fread (content, sizeof (char), filesize, fp);
  1071.     fclose (fp);
  1072.  
  1073.     return (content);
  1074. }
  1075.  
  1076.  
  1077.  
  1078. void Tini (void)
  1079. {
  1080.     SoundTini0 ();
  1081.     _iocs_ms_init ();
  1082.     _iocs_ms_curof ();
  1083.     if (screen_init)
  1084.         _iocs_crtmod (16);
  1085.     _dos_kflushio (0xff);    /* キーバッファをクリア */
  1086.     _dos_c_curon ();
  1087.     _iocs_skey_mod (-1, 0, 0);
  1088. }
  1089.  
  1090.  
  1091.  
  1092. int Init (char *fname)
  1093. {
  1094.     int i, j;
  1095.     int sp;
  1096.     int track, note_abs;
  1097.  
  1098.     bar_max = 0;        /* 最大の小節数 */
  1099.     note_tempo = 6;        /* この回数垂直同期を待つごとに発音(16分音符) */
  1100.  
  1101.     {
  1102.         int table[BAR_MAX_TABLE] =
  1103.         {1, 2, 4, 8, BAR_MAX};
  1104.         for (i = 0; i < BAR_MAX_TABLE; i++)
  1105.             bar_max_table[i] = table[i];
  1106.     }
  1107.     if (Pcm8KeepCheck ()) {
  1108.         printf ("PCM8 が常駐していません\n");
  1109.         return (-1);
  1110.     }
  1111.     /* 演奏データを初期化 */
  1112.     for (track = 0; track < TRACK_MAX; track++) {
  1113.         for (note_abs = 0; note_abs < BAR_MAX * NOTE_DISP; note_abs++) {
  1114.             note_volume[track][note_abs] = 0;
  1115.             note_type[track][note_abs] = 0;
  1116.         }
  1117.     }
  1118.  
  1119.     if (SoundInit0 (fname))
  1120.         return (-1);
  1121.  
  1122.     /* .ZMS 読み込み */
  1123.     if (fname == NULL) {
  1124.         /* TR68K.ZMS 読み込み */
  1125.         if (SoundLoadZms ("TR68K.ZMS") < 0) {
  1126.             char temp_fname[92];
  1127.             /* 実行ファイルと同じパスにしてもう1回オープン */
  1128.             strcpy (temp_fname, mypsp->exe_path);
  1129.             _addlastsep (temp_fname);
  1130.             strcat (temp_fname, "TR68K.ZMS");
  1131.             if (SoundLoadZms (temp_fname) < 0) {
  1132.                 printf ("TR68K.ZMS を読み込めません\n");
  1133.                 return (-1);
  1134.             }
  1135.         }
  1136.     } else {
  1137.         if (SoundLoadZms (fname) < 0) {
  1138.             printf ("%s を読み込めません\n", fname);
  1139.             return (-1);
  1140.         }
  1141.     }
  1142.  
  1143.     sp_data = LoadFile ("TR68K.SP");
  1144.     if (sp_data == NULL)
  1145.         return (-1);
  1146.  
  1147.     pal_data = LoadFile ("TR68K.PAL");
  1148.     if (pal_data == NULL)
  1149.         return (-1);
  1150.  
  1151.     _iocs_crtmod (12);
  1152.     _iocs_g_clr_on ();
  1153.     _iocs_sp_init ();
  1154.     if (apic_load ("TR68K.PIC", 0, 0)) {
  1155.         char temp_fname[92];
  1156.         strcpy (temp_fname, mypsp->exe_path);
  1157.         _addlastsep (temp_fname);
  1158.         strcat (temp_fname, "TR68K.PIC");
  1159.         if (apic_load (temp_fname, 0, 0)) {
  1160.             printf ("TR68K.PIC を読み込めません\n");
  1161.             return (-1);
  1162.         }
  1163.     }
  1164.     screen_init = !0;
  1165.  
  1166.     _dos_c_curoff ();
  1167.  
  1168.     _iocs_ms_init ();
  1169.     _iocs_skey_mod (0, 0, 0);
  1170.     _iocs_ms_curon ();
  1171.  
  1172.     /* スプライトパターンの設定 */
  1173.     {
  1174.         char *sp_ptr = sp_data;
  1175.         for (i = 0; i < 0x60; i++) {
  1176.             _iocs_sp_defcg (i, 1, sp_ptr);
  1177.             sp_ptr += 128;
  1178.         }
  1179.     }
  1180.  
  1181.     /* パレットデータの設定 */
  1182.     {
  1183.         unsigned short *pal_ptr = (unsigned short *) pal_data;
  1184.         for (i = 1; i < 7; i++)
  1185.             for (j = 0; j < 16; j++)
  1186.                 _iocs_spalet (0x80000000 + j, i, *pal_ptr++);    /* 垂直同期検出なし */
  1187.         /*      _iocs_spalet (0x80 + j, i, *pal_ptr++); LIBC のマニュアルは間違い */
  1188.     }
  1189.  
  1190.     _iocs_sp_on ();
  1191.     _iocs_bgctrlst (0, 0, 1);
  1192.  
  1193.     sp = _iocs_b_super (0);
  1194.     *(unsigned short *) 0xe82500 = 0b01001011100100;    /* 優先順位 TX>SP>GR */
  1195.     _iocs_b_super (sp);
  1196.  
  1197.  
  1198.     /* トラックアクティブ状態を初期化(全部アクティブに) */
  1199.     for (i = 0; i < TRACK_MAX; i++) {
  1200.         track_active[i] = !0;
  1201.         DispTrackActive (i);
  1202.     }
  1203.  
  1204.     /* コピーバッファを初期化 */
  1205.     for (track = 0; track < TRACK_MAX; track++) {
  1206.         for (i = 0; i < NOTE_DISP; i++) {
  1207.             copy_type[track][i] = 0;
  1208.             copy_volume[track][i] = 0;
  1209.         }
  1210.     }
  1211.  
  1212.     DispScore (0);
  1213.     DispFname ();
  1214.  
  1215.     return (0);
  1216. }
  1217.  
  1218.  
  1219.  
  1220. int main (int argc, char *argv[])
  1221. {
  1222.     int i;
  1223.     int slash_flag = 0;
  1224.     char *fname = NULL;    /* .ZMS ファイル名 */
  1225.  
  1226.     mypsp = _dos_getpdb ();
  1227.     {
  1228.         char *temp;
  1229.  
  1230.         temp = getenv ("SLASH");
  1231.         if ((temp != NULL) && (*temp == '/'))
  1232.             slash_flag = !0;
  1233.     }
  1234.     for (i = 1; i < argc; i++) {
  1235.         if (('-' == *argv[i]) || ((!slash_flag) && ('/' == *argv[i]))) {
  1236.             switch (*(argv[i] + 1)) {
  1237.             default:
  1238.                 usage ();
  1239.                 return (-1);
  1240.             }
  1241.         } else {
  1242.             fname = argv[i];
  1243.         }
  1244.     }
  1245.     if (!Init (fname))
  1246.         EventLoop (fname);
  1247.     Tini ();
  1248.     return (0);
  1249. }
  1250.